/**
 * @author Rid King
 * @since 2018-07-06
 * @version 2.0.1
 * @description 对象模块
 */
const objecter = {
	// 对象类型
	_types : {
		'[object Boolean]': 'boolean',
		'[object Number]': 'number',
		'[object String]': 'string',
		'[object Function]': 'function',
		'[object Array]': 'array',
		'[object Date]': 'date',
		'[object RegExp]': 'regExp',
		'[object Object]': 'object',
		'[object Null]': 'null',
		'[object Undefined]': 'undefined'
	},

	/**
	 * 检测v的类型
	 * @param {Any} v 被检测的变量
	 * @return {String}
	 */
	_type (v) {
		return Object.prototype.toString.call(v);
	},

	/**
	 * 是否为字符串类型 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isString (v) {
		return typeof v === 'string';
	},

	/**
	 * 是否为数字类型(为Number且不为正负无穷大数字) 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isNumber (v) {
		return typeof v === 'number' && isFinite(v);
	},

	/**
	 * 是否为布尔值类型  如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isBoolean (v) {
		return typeof v === 'boolean';
	},

	/**
	 * 是否为正则表达式类型  如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isRegexp (v) {
		return this._type(v) === '[object RegExp]';
	},

	/**
	 * 是否为函数类型 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isFunction (v) {
		return this._type(v) === '[object Function]';
	},

	/**
	 * 是否为数组对象类型  如果是就返回true 如果不是就返回false
	 * @method isArray
	 * @param {Any} v 被检测的变量
	 * @return {Boolean} 结果
	 */
	isArray (v) {
		return this._type(v) === '[object Array]';
	},

	/**
	 * 是否为对象类型
	 * @param {Any} v 被检测的变量
	 * @return {boolean}
	 */
	isObject (v) {
		return !!v && typeof v === 'object';
	},

	/**
	 * 是否为纯对象类型
	 * @param {Any} v 被检测的变量
	 * @return {boolean}
	 */
	isPlainObject (v) {
		return !!v && this._type(v) === '[object Object]';
	},

	/**
	 * 是否为null
	 * @param {Any} v 被检测的变量
	 * @return {boolean}
	 */
	isNull (v) {
		return null === null && this._type(v) === '[object Null]';
	},

	/**
	 * 是否为日期类型  如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {boolean}
	 */
	isDate (v) {
		return this._type(v) === '[object Date]';
	},

	/**
	 * 是否为空对象 null和undefined和数组的长度为0或空字符串("") 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @param {Boolean} allowBlank [可选] 默认false 空字符串认为是空对象 反之 空字符串不认为是空对象
	 * @return {Boolean}
	 */
	isEmpty (v, allowBlank) {
		return v === null || v === undefined ||
			(this.isArray(v) && !v.length) ||
			(!allowBlank ? v === '' : false);
	},

	/**
	 * 是否为空对象 null和undefined和数组的长度为0或空字符串("") 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @param {Boolean} allowBlank [可选] 默认false 空字符串认为是空对象 反之 空字符串不认为是空对象
	 * @return {Boolean}
	 */
	IsNullOrEmpty (obj) {
		var flag = false;
		if (obj == null || obj == undefined || typeof (obj) == 'undefined' || obj == '') {
			flag = true;
		} else if (typeof (obj) == 'string') {
			obj = obj.trim();
			if (obj == '') {//为空
				flag = true;
			} else {//不为空
				obj = obj.toUpperCase();
				if (obj == 'NULL' || obj == 'UNDEFINED' || obj == '{}') {
					flag = true;
				}
			}
		}
		else {
			flag = false;
		}
		return flag;
	},

	/**
	 * 是否为参数管理器Arguments 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isArguments (v) {
		return v.callee !== undefined;
	},

	/**
	 * 是否为迭代序列 包含Array与Arguments 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isIterable (v) {
		return this.isArray(v) || this.isArguments(v);
	},

	/**
	 * 是否为原始数据类型 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isPrimitive (v) {
		return this.isString(v) || this.isNumber(v) ||
			this.isBoolean(v);
	},

	/**
	 * 是否为window 如果是就返回true 如果不是就返回false
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isWindow (v) {
		return v && typeof v === "object" && "setInterval" in v;
	},

	/**
	 * 是否为DOM元素
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isDOM (v) {
		var func = ( typeof HTMLElement === 'object' ) ?
			function(obj){
				return obj instanceof HTMLElement;
			} :
			function(obj){
				return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
			}

		return func(v);
	},

	/**
	 * 是否为DOM元素节点
	 * @param {Any} v 被检测的变量
	 * @return {Boolean}
	 */
	isElementNode (node) {
		return node && node.nodeType === 1;
		/*
			节点类型	nodeType属性值
			元素节点	1
			属性节点	2
			文本节点	3
			*/
	},

	/**
	 * 继承
	 * @param {Boolean} b 是否深复制
	 * @return {Object} arg1 复制的对象1
	 * @return {Object} arg2 复制的对象2
	 */
	extend (b, arg1, arg2) {
		var options, name, src, copy, copyIsArray, clone,
			target = arguments[0] || {},
			i = 1,
			length = arguments.length,
			deep = false;

		if ( typeof target === "boolean" ) {
			deep = target;
			target = arguments[1] || {};
			i = 2;
		}

		if ( typeof target !== "object" && !this.isFunction(target) ) {
			target = {};
		}

		if ( length === i ) {
			target = this;
			--i;
		}

		for ( ; i < length; i++ ) {
			options = arguments[ i ];
			if ( options !== null && this.isObject(options) && !this.isDOM(options) && !this.isElementNode(options)) {
				for ( name in options ) {
					src = target[ name ];
					copy = options[ name ];
					if ( target === copy ) {
						continue;
					}
					if ( deep && copy && ( this.isPlainObject(copy) || (copyIsArray = this.isArray(copy)) ) ) {
						if ( copyIsArray ) {
							copyIsArray = false;
							clone = src && this.isArray(src) ? src : [];
						} else {
							clone = src && this.isPlainObject(src) ? src : {};
						}
						target[ name ] = this.extend( deep, clone, copy );
					} else if ( copy !== undefined ) {
						target[ name ] = copy;
					}
				}
			}
		}
		return target
	},

	//克隆
	clone (obj) {
		var o;
		switch(typeof obj){
			case 'undefined': break;
			case 'string'   : o = obj + '';break;
			case 'number'   : o = obj - 0;break;
			case 'boolean'  : o = obj;break;
			case 'object'   :
				if(obj === null){
					o = null
				}else{
					if(obj instanceof Array){
						o = []
						for(var i = 0, len = obj.length; i < len; i++){
							o.push(this.clone(obj[i]))
						}
					}else{
						o = {};
						for(var k in obj){
							o[k] = this.clone(obj[k])
						}
					}
				}
				break
			default:
				o = obj;break
		}
		return o
	},

	/*
	* 遍历
	*/
	forEach (obj, func) {
		if (this.isArray(obj)) {
			for (var i = 0; i < obj.length; i++) {
				var b = func(obj[i], i, obj)
				if (b === false) {
					break
				}
			}
		} else if (this.isString(obj)) {
			var n = 0
			for (var item in obj) {
				var b = func(obj[item], n, obj)
				n += 1
				if (b === false) {
					break
				}
			}
		} else if (typeof obj === 'object' && obj !== null) {
			for (var property in obj) {
				if (obj.hasOwnProperty(property)) {
					var b = func(obj[property], property, obj)
					if (b === false) {
						break
					}
				}
			}
		}
	}
}

export default objecter